package com.sukaiyi.generator.processor;

import cn.hutool.json.JSONUtil;
import com.sukaiyi.generator.config.model.StructTemplate;
import com.sukaiyi.generator.config.model.TplType;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.output.StringBuilderWriter;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

public class TemplateProcessor {
    private static final TemplateProcessor INSTANCE = new TemplateProcessor();

    private TemplateProcessor() {
    }

    public static TemplateProcessor getInstance() {
        return INSTANCE;
    }

    public StructTemplate process(Map<String, Object> dataModel, StructTemplate template) throws IOException, TemplateException {
        List<StructTemplate> children = template.getChildren();
        assert children != null && children.size() > 0;
        String json = JSONUtil.toJsonStr(template);
        StructTemplate copyTemplate = JSONUtil.toBean(json, StructTemplate.class);
        handleStructTemplate(dataModel, copyTemplate);
        return copyTemplate;
    }

    private void handleStructTemplate(Map<String, Object> dataModel, StructTemplate template) throws IOException, TemplateException {
        StringTemplateLoader loader = new StringTemplateLoader();
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setTemplateLoader(loader);

        Queue<StructTemplate> templateQueue = new LinkedList<>(template.getChildren());
        while (!templateQueue.isEmpty()){
            StructTemplate structTemplate = templateQueue.poll();
            String cur = System.currentTimeMillis() + structTemplate.getName() + "[title]";
            loader.putTemplate(cur, structTemplate.getName());
            Template tpl = configuration.getTemplate(cur, "utf-8");
            StringBuilderWriter writer = new StringBuilderWriter();
            tpl.process(dataModel, writer);
            structTemplate.setName(writer.toString());

            if (structTemplate.getType() == TplType.MODULE) {
                if (structTemplate.getChildren() != null && structTemplate.getChildren().size() > 0) {
                    templateQueue.addAll(structTemplate.getChildren());
                }
                continue;
            }
            cur = cur + "[content]";
            loader.putTemplate(cur, structTemplate.getContent());
            tpl = configuration.getTemplate(cur, "utf-8");
            writer = new StringBuilderWriter();
            tpl.process(dataModel, writer);
            structTemplate.setContent(writer.toString());
        }
    }
}
